﻿using System;
//using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
//using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Caculator {
	public partial class MainForm : Form {
		#region Fields
		private StringBuilder expressionBuilder = new StringBuilder(""); // Tao bieu thuc truoc khi tinh
		private StringBuilder inputString = new StringBuilder(""); // Xu li chuoi dau vao
		private Expressions ex = new Expressions(""); // Doi tuong de tinh gia tri bieu thuc
		private bool _ir = false; // Xac nhan da tinh bieu thuc nao chua
		private double mem = 0;
		#endregion

		public MainForm() {
			InitializeComponent();
		}

		#region Number Buttons
		private void btn0_Click(object sender, EventArgs e) {
			if (_ir == true) {
				inputString.Remove(0, inputString.Length);
				this.txtInput.Text = "0";
				_ir = false;
			}
			if (this.txtInput.Text != "0") {
				inputString.Append("0");
				this.txtInput.Text = inputString.ToString();
			}
		}

		private void btn1_Click(object sender, EventArgs e) {
			if (_ir == true) {
				inputString.Remove(0, inputString.Length);
				this.txtInput.Text = "0";
				_ir = false;
			}
			if (inputString.ToString() == "0") {
				inputString.Remove(0, 1);
			}
			inputString.Append("1");
			this.txtInput.Text = inputString.ToString();
		}

		private void btn2_Click(object sender, EventArgs e) {
			if (_ir == true) {
				inputString.Remove(0, inputString.Length);
				this.txtInput.Text = "0";
				_ir = false;
			}
			if (inputString.ToString() == "0") {
				inputString.Remove(0, 1);
			}
			inputString.Append("2");
			this.txtInput.Text = inputString.ToString();
		}

		private void btn3_Click(object sender, EventArgs e) {
			if (_ir == true) {
				inputString.Remove(0, inputString.Length);
				this.txtInput.Text = "0";
				_ir = false;
			}
			if (inputString.ToString() == "0") {
				inputString.Remove(0, 1);
			}
			inputString.Append("3");
			this.txtInput.Text = inputString.ToString();
		}

		private void btn4_Click(object sender, EventArgs e) {
			if (_ir == true) {
				inputString.Remove(0, inputString.Length);
				this.txtInput.Text = "0";
				_ir = false;
			}
			if (inputString.ToString() == "0") {
				inputString.Remove(0, 1);
			}
			inputString.Append("4");
			this.txtInput.Text = inputString.ToString();
		}

		private void btn5_Click(object sender, EventArgs e) {
			if (_ir == true) {
				inputString.Remove(0, inputString.Length);
				this.txtInput.Text = "0";
				_ir = false;
			}
			if (inputString.ToString() == "0") {
				inputString.Remove(0, 1);
			}
			inputString.Append("5");
			this.txtInput.Text = inputString.ToString();
		}

		private void btn6_Click(object sender, EventArgs e) {
			if (_ir == true) {
				inputString.Remove(0, inputString.Length);
				this.txtInput.Text = "0";
				_ir = false;
			}
			if (inputString.ToString() == "0") {
				inputString.Remove(0, 1);
			}
			inputString.Append("6");
			this.txtInput.Text = inputString.ToString();
		}

		private void btn7_Click(object sender, EventArgs e) {
			if (_ir == true) {
				inputString.Remove(0, inputString.Length);
				this.txtInput.Text = "0";
				_ir = false;
			}
			if (inputString.ToString() == "0") {
				inputString.Remove(0, 1);
			}
			inputString.Append("7");
			this.txtInput.Text = inputString.ToString();
		}

		private void btn8_Click(object sender, EventArgs e) {
			if (_ir == true) {
				inputString.Remove(0, inputString.Length);
				this.txtInput.Text = "0";
				_ir = false;
			}
			if (inputString.ToString() == "0") {
				inputString.Remove(0, 1);
			}
			inputString.Append("8");
			this.txtInput.Text = inputString.ToString();
		}

		private void btn9_Click(object sender, EventArgs e) {
			if (_ir == true) {
				inputString.Remove(0, inputString.Length);
				this.txtInput.Text = "0";
				_ir = false;
			}
			if (inputString.ToString() == "0") {
				inputString.Remove(0, 1);
			}
			inputString.Append("9");
			this.txtInput.Text = inputString.ToString();
		}

		private void btnDot_Click(object sender, EventArgs e) {
			if (_ir == true) {
				inputString.Remove(0, inputString.Length);
				this.txtInput.Text = "0";
				_ir = false;
			}
			if (inputString.ToString().IndexOf('.') > -1) {
				// Bao da co dau cham roi
				//MessageBox.Show("Đã sử dụng dấu chấm rồi!");
			}
			else {
				if (inputString.ToString() == "") {
					inputString.Append("0");
				}
				inputString.Append(".");
				this.txtInput.Text = inputString.ToString();
			}
		}

		private void btnAddSubtract_Click(object sender, EventArgs e) {
			if (this.txtInput.Text != "" && this.txtInput.Text.Length > 0 && this.txtInput.Text != "0") {
				if (this.txtInput.Text.StartsWith("~")) {
					inputString.Remove(0, 1);
				}
				else {
					inputString.Insert(0, "~");
				}
			}
			this.txtInput.Text = inputString.ToString();
		}
		#endregion

		#region Operator Methods
		private void btnAdd_Click(object sender, EventArgs e) {
			if (_ir == true) {
				expressionBuilder.Remove(0, expressionBuilder.Length);
				_ir = false;
			}
			expressionBuilder.Append(this.txtInput.Text);
			expressionBuilder.Append("+");
			this.lblShowExpression.Text = expressionBuilder.ToString();
			this.txtInput.Text = "";
		}

		private void btnSubtract_Click(object sender, EventArgs e) {
			if (_ir == true) {
				expressionBuilder.Remove(0, expressionBuilder.Length);
				_ir = false;
			}
			expressionBuilder.Append(this.txtInput.Text + "-");
			this.txtInput.Text = "";
			this.lblShowExpression.Text = expressionBuilder.ToString();
		}

		private void btnMul_Click(object sender, EventArgs e) {
			if (_ir == true) {
				expressionBuilder.Remove(0, expressionBuilder.Length);
				_ir = false;
			}
			expressionBuilder.Append(this.txtInput.Text + "*");
			this.txtInput.Text = "";
			this.lblShowExpression.Text = expressionBuilder.ToString();
		}

		private void btnDiv_Click(object sender, EventArgs e) {
			if (_ir == true) {
				expressionBuilder.Remove(0, expressionBuilder.Length);
				_ir = false;
			}
			expressionBuilder.Append(this.txtInput.Text + "/");
			this.txtInput.Text = "";
			this.lblShowExpression.Text = expressionBuilder.ToString();
		}

		private void btnMod_Click(object sender, EventArgs e) {
			if (_ir == true) {
				expressionBuilder.Remove(0, expressionBuilder.Length);
				_ir = false;
			}
			expressionBuilder.Append(this.txtInput.Text + "%");
			this.txtInput.Text = "";
			this.lblShowExpression.Text = expressionBuilder.ToString();
		}

		private void btnSquareRoot_Click(object sender, EventArgs e) {
			expressionBuilder.Remove(0, expressionBuilder.Length);
			expressionBuilder.Append("sqrt(");
			expressionBuilder.Append(txtInput.Text);
			expressionBuilder.Append(")");
			ex.Expression = expressionBuilder.ToString();
			double v = ex.evaluateExpression();
			txtInput.Text = v.ToString();
			_ir = true;
		}

		private void btnInverse_Click(object sender, EventArgs e) {
			if (_ir == true) {
				expressionBuilder.Remove(0, expressionBuilder.Length);
				_ir = false;
			}
			if (txtInput.Text != "") {
				expressionBuilder.Insert(0, "1/");
				expressionBuilder.Append(txtInput.Text);
				lblShowExpression.Text = expressionBuilder.ToString();
				txtInput.Text = "";
			}
		}
		#endregion

		#region Mem
		private void btnMC_Click(object sender, EventArgs e) {
			this.lblM.Text = "";
			this.mem = 0;
		}

		private void btnMR_Click(object sender, EventArgs e) {
			this.txtInput.Text = this.mem.ToString();
		}

		private void btnMS_Click(object sender, EventArgs e) {
			this.lblM.Text = "M";
			this.mem = Convert.ToDouble(this.txtInput.Text);
			_ir = true;
		}

		private void btnMAdd_Click(object sender, EventArgs e) {
			try {
				this.mem += Convert.ToDouble(this.txtInput.Text);
			}
			catch {
				this.lblShowExpression.Text = "Math error!";
			}
			
		}

		private void btnMSubtract_Click(object sender, EventArgs e) {
			try {
				this.mem -= Convert.ToDouble(this.txtInput.Text);
			}
			catch {
				this.lblShowExpression.Text = "Math error!";
			}
		}
		#endregion

		#region Clear
		private void btnCE_Click(object sender, EventArgs e) {
			_ir = false;
			txtInput.Text = "0";
			lblShowExpression.Text = "";
			expressionBuilder.Remove(0, expressionBuilder.Length);
		}

		private void btnC_Click(object sender, EventArgs e) {
			_ir = false;
			txtInput.Text = "0";
			lblShowExpression.Text = "";
			expressionBuilder.Remove(0, expressionBuilder.Length);
		}
		#endregion

		#region Equal Button
		private void btnEqual_Click(object sender, EventArgs e) {
			this.lblShowExpression.Text = expressionBuilder.ToString();
			ex.Expression = expressionBuilder.ToString();
			if (Double.IsNaN(ex.evaluateExpression()) || Double.IsInfinity(ex.evaluateExpression())) {
				this.lblShowExpression.Text = "Expression is invalid!";
				this.txtInput.Text = ex.Expression;
			}
			else {
				this.txtInput.Text = ex.evaluateExpression().ToString();
				//this.lblShowExpression.Text = "";
			}
			inputString.Remove(0, inputString.Length);
			//_ir = true;
		}

		private void btnEqual_MouseDown(object sender, MouseEventArgs e) {
			if (_ir == false) {
				expressionBuilder.Append(this.txtInput.Text);
				_ir = true;
			}
			else if (expressionBuilder.ToString() != "" && (this.txtInput.Text != "0" || this.txtInput.Text == "")) expressionBuilder.Insert(0, this.txtInput.Text);
		}

		private void btnEqual_MouseUp(object sender, MouseEventArgs e) {
			int i = ex.Expression.Length - 1;
			expressionBuilder.Remove(0, expressionBuilder.Length);
			expressionBuilder.Append(ex.Expression);
			while (i > -1 && (Char.IsDigit(expressionBuilder[i]) || expressionBuilder[i] == '.')) i--;
			if (i > -1) expressionBuilder.Remove(0, i);
			//_ir = true;
		}
		#endregion

		#region Unit
		private void setUnit(int unit) {
			switch (unit) {
				case 0: this.rdbDegrees.Checked = true; break;
				case 1: this.rdbRadians.Checked = true; break;
				case 2: this.rdbGrads.Checked = true; break;
			}
		}

		private void rdbDegrees_CheckedChanged(object sender, EventArgs e) {
			if (rdbDegrees.Checked == true) {
				//MessageBox.Show(ex.Unit.ToString());
				ex.Unit = 0;
				//MessageBox.Show(ex.Unit.ToString());
			}
		}

		private void rdbRadians_CheckedChanged(object sender, EventArgs e) {
			if (rdbRadians.Checked == true) {
				//MessageBox.Show(ex.Unit.ToString());
				ex.Unit = 1;
				//MessageBox.Show(ex.Unit.ToString());
			}
		}

		private void rdbGrads_CheckedChanged(object sender, EventArgs e) {
			if (rdbGrads.Checked == true) {
				//MessageBox.Show(ex.Unit.ToString());
				ex.Unit = 2;
				//MessageBox.Show(ex.Unit.ToString());
			}
		}
		#endregion

		#region sin, cos, tan, cot
		private void btnSin_Click(object sender, EventArgs e) {
			expressionBuilder.Remove(0, expressionBuilder.Length);
			expressionBuilder.Append("sin(");
			expressionBuilder.Append(this.txtInput.Text);
			expressionBuilder.Append(")");
			ex.Expression = expressionBuilder.ToString();
			double v = ex.evaluateExpression();
			if (Double.IsNaN(v) || Double.IsInfinity(v) || Double.IsNegativeInfinity(v) || Double.IsPositiveInfinity(v)) {
				lblShowExpression.Text = "Invalid input!";
				txtInput.Text = ex.Expression;
			}
			else txtInput.Text = v.ToString();
			_ir = true;
		}

		private void btnCos_Click(object sender, EventArgs e) {
			expressionBuilder.Remove(0, expressionBuilder.Length);
			expressionBuilder.Append("cos(");
			expressionBuilder.Append(this.txtInput.Text);
			expressionBuilder.Append(")");
			ex.Expression = expressionBuilder.ToString();
			double v = ex.evaluateExpression();
			if (Double.IsNaN(v) || Double.IsInfinity(v) || Double.IsNegativeInfinity(v) || Double.IsPositiveInfinity(v)) {
				lblShowExpression.Text = "Invalid input!";
				txtInput.Text = ex.Expression;
			}
			else txtInput.Text = v.ToString();
			_ir = true;
		}

		private void btnTan_Click(object sender, EventArgs e) {
			expressionBuilder.Remove(0, expressionBuilder.Length);
			expressionBuilder.Append("tan(");
			expressionBuilder.Append(this.txtInput.Text);
			expressionBuilder.Append(")");
			ex.Expression = expressionBuilder.ToString();
			double v = ex.evaluateExpression();
			if (Double.IsNaN(v) || Double.IsInfinity(v) || Double.IsNegativeInfinity(v) || Double.IsPositiveInfinity(v)) {
				lblShowExpression.Text = "Invalid input!";
				txtInput.Text = ex.Expression;
			}
			else txtInput.Text = v.ToString();
		}

		private void btnCotan_Click(object sender, EventArgs e) {
			expressionBuilder.Remove(0, expressionBuilder.Length);
			expressionBuilder.Append("cot(");
			expressionBuilder.Append(this.txtInput.Text);
			expressionBuilder.Append(")");
			ex.Expression = expressionBuilder.ToString();
			double v = ex.evaluateExpression();
			if (Double.IsNaN(v) || Double.IsInfinity(v) || Double.IsNegativeInfinity(v) || Double.IsPositiveInfinity(v)) {
				lblShowExpression.Text = "Invalid input!";
				txtInput.Text = ex.Expression;
			}
			else txtInput.Text = v.ToString();
		}
		#endregion

		private void txtBackSpace_Click(object sender, EventArgs e) {
			if (txtInput.Text.Length > 1 && txtInput.Text != "0") {
				inputString.Remove(0, inputString.Length);
				inputString.Append(txtInput.Text);
				inputString.Remove(inputString.Length - 1, 1);
				txtInput.Text = inputString.ToString();
			}
			else txtInput.Text = "0";
		}
		
		private void txtInput_TextChanged(object sender, EventArgs e) {
			inputString.Remove(0, inputString.Length);
			inputString.Append(txtInput.Text);
		}

		private void setMode(string _mode) {
			switch (_mode) {
				case "basic":
				case "BASIC": {
					this.Size = new Size(231, 320);
					this.grbContainer.Size = new Size(187, grbContainer.Size.Height);
					this.txtInput.Size = new Size(182, txtInput.Size.Height);
					this.lblShowExpression.Size = new Size(182, lblShowExpression.Size.Height);
					this.pnlAdvanced.Visible = false;
					this.pnlBasic.Location = new Point(12, 70);
				} break;
				case "advanced":
				case "ADVANCED": {
					this.Size = new Size(420, 320);
					this.grbContainer.Size = new Size(380, grbContainer.Size.Height);
					this.txtInput.Size = new Size(372, txtInput.Size.Height);
					this.lblShowExpression.Size = new Size(372, lblShowExpression.Size.Height);
					this.pnlAdvanced.Visible = true;
					this.pnlBasic.Location = new Point(208, 70);
				} break;
				default: break;

			}
		}
		
		private void MainForm_Load(object sender, EventArgs e) {
			setMode("basic");
			setUnit(0);
		}

		private void btnPI_Click(object sender, EventArgs e) {
			txtInput.Text = Math.PI.ToString();
		}

		private void miBasic_Click(object sender, EventArgs e)
		{
			setMode("basic");
		}

		private void miAdvanced_Click(object sender, EventArgs e)
		{
			setMode("advanced");
		}

		private void miViewHelpClick(object sender, EventArgs e)
		{
			MessageBox.Show("You are viewing help!","Message!", MessageBoxButtons.OK, MessageBoxIcon.Information);
		}
		
	}
}
